﻿///////////////////////////////////////////////////////////////////////////////
/// Copyright (c) by longshuang@msn.cn 2014.
/// All rights reserved.
///
/// @File	: Engine.Network.hpp
/// @Brief	: 网络层封装
/// @Author	: Leo Zhao <longshuang@msn.cn>
/// @Date	: 2014-12-18
///
/// CHANGELOG
/// 	2014-12-18	接口定义
///////////////////////////////////////////////////////////////////////////////
#ifndef		__ENGINE_NETWORK_HPP_INCLUDE__
#define		__ENGINE_NETWORK_HPP_INCLUDE__

#include	<cstddef>
#include	<cstdint>
#include	<string>

namespace Engine { namespace Network {

	/// @Brief	: 附加错误状态描述
	enum {
		Success		= 0,		//! 操作成功
		ErrParam	= 65536,	//! 参数错误
		ErrAlreadyUsed,			//! 正在使用中
		ErrAlloc,				//! 申请内存失败
		ErrCreateThread,		//! 创建工作线程时失败
		ErrInvalidConnId,		//! nConnId不正确
		ErrTimeOut,				//! 超时
	};

	/// @Brief	: 接收缓冲区大小
	enum {
		ReceiveBuffer = 256 * 1024
	};

	/// @Brief	: 关闭的原因
	enum ECloseReason {
		SystemClose = 0,
		ClientClose,
		DataError,
	};

	/// @Brief	: 网络TCP通信Client封装
	class Socket {
	public:
		struct IListener;

	public:
		virtual ~Socket() {}

		/// @Brief	: 启动一个独立的线程监听
		/// @Param	: pStrIp	监听的本机IP
		/// @Param	: uPort		监听的本机端口
		/// @Param	: pListener	消息处理逻辑
		/// @Return	: 返回监听状态 0成功，其他为错误代码
		virtual int		Connect(const char * pStrIp, unsigned short uPort, IListener * pListener) = 0;

		/// @Brief	: 发送数据给指定连接
		/// @Param	: pData		要发送的数据头地址
		/// @Param	: uSize		发送的数据的大小
		/// @Return	: 返回发送状态 0成功，其他为错误代码
		virtual int		Send(const char * pData, size_t uSize) = 0;
		
	public:
		/// @Brief	: 请使用该方法得到一个ServerSocket对象
		/// @Param	: nConnId	连接ID
		/// @Return	: NONE
		static Socket *	Create();

		/// @Brief	: 启动一个独立的线程监听
		/// @Param	: pClient	对象指针
		/// @Param	: nReason	关闭的原因
		/// @Return	: NONE
		static void		Close(Socket * pClient, int nReason);
	};

	/// @Brief	: 通信消息处理接口定义 - 客户端，异步
	struct Socket::IListener {

		/// @Brief	: 接口定义 - 连接成功时回调
		/// @Param	: uRemoteIp	远程连接IP
		/// @Param	: uPort		远程连接Port
		/// @Return	: NONE
		virtual void	OnConnect(uint32_t uRemoteIp, uint16_t uPort) = 0;

		/// @Brief	: 接口定义 - 收到数据时回调
		/// @Param	: pData		数据
		/// @Param	: uSize		数据的大小
		/// @Return	: 返回数据处理的结果，True已处理;false未处理
		/// @Note	: 对于并发数量高且对执行顺序要求很高的程序，OnReceive中尽量不要处理事务，仅作为数据的转存接口。
		///			而将数据的业务处理放在主循环中（如定义一个Breath接口)
		virtual bool	OnReceive(char * pData, size_t uSize) = 0;

		/// @Brief	: 接口定义 - 特定连接被关闭时回调
		/// @Param	: nReason	触发关闭的条件
		/// @Return	: NONE
		virtual void	OnClose(int nReason) = 0;

		IListener() : pSender(nullptr) {}
		virtual ~IListener() {}

		Socket *	pSender;
	};

	/// @Brief	: 网络TCP通信Server封装
	class ServerSocket {
	public:
		struct IListener;

	public:
		virtual ~ServerSocket() {}

		/// @Brief	: 启动一个独立的线程监听
		/// @Param	: pStrIp	监听的本机IP
		/// @Param	: uPort		监听的本机端口
		/// @Param	: pListener	消息处理逻辑
		/// @Return	: 返回监听状态 0成功，其他为错误代码
		virtual int		Listen(const char * pStrIp, unsigned short uPort, IListener * pListener) = 0;

		/// @Brief	: 发送数据给指定连接
		/// @Param	: nConnId	指定的连接ID
		/// @Param	: pData		要发送的数据头地址
		/// @Param	: uSize		发送的数据的大小
		/// @Return	: 返回发送状态 0成功，其他为错误代码
		virtual int		Send(uint64_t nConnId, const char * pData, size_t uSize) = 0;

		/// @Brief	: 给当前所有的连接发送消息
		/// @Param	: pData		要发送的信息
		/// @Param	: uSize		发送的数据的大小
		/// @Return	: 返回发送的状态 0成功，其他为错误代码
		virtual int		Broadcast(const char * pData, size_t uSize) = 0;

		/// @Brief	: 关闭一个连接
		/// @Param	: nConnId	连接ID
		/// @Param	: nReason	关闭的原因
		/// @Return	: NONE
		virtual void	Close(uint64_t nConnId, int nReason) = 0;

	public:
		/// @Brief	: 请使用该方法得到一个ServerSocket对象
		/// @Param	: nConnId	连接ID
		/// @Return	: NONE
		static ServerSocket *	Create();

		/// @Brief	: 启动一个独立的线程监听
		/// @Param	: pServer	对象指针
		/// @Return	: NONE
		static void				Shutdown(ServerSocket * pServer);
	};
	
	/// @Brief	: 通信消息处理接口定义 - 服务器端，异步
	struct ServerSocket::IListener {

		/// @Brief	: 接口定义 - 新的连接到来时回调
		/// @Param	: nConnId	连接ID
		/// @Param	: uRemoteIp	远程IP
		/// @Param	: uPort		远程Port
		/// @Param	: nState	连接状态，0成功，其他为错误码
		/// @Return	: NONE
		virtual void	OnAccept(uint64_t nConnId, uint32_t uRemoteIp, uint16_t uPort, int nState) = 0;

		/// @Brief	: 接口定义 - 收到数据时回调
		/// @Param	: nConnId	数据来源ID
		/// @Param	: pData		数据
		/// @Param	: uSize		数据的大小
		/// @Return	: 返回数据处理的结果，True已处理;false未处理
		/// @Note	: 对于并发数量高且对执行顺序要求很高的程序，OnReceive中尽量不要处理事务，仅作为数据的转存接口
		///			而将数据的业务处理放在主循环中（如定义一个Breath接口)
		virtual bool	OnReceive(uint64_t nConnId, char * pData, size_t uSize) = 0;

		/// @Brief	: 接口定义 - 特定连接被关闭时回调
		/// @Param	: nConnId	关闭的连接ID
		/// @Param	: nReason	触发关闭的条件
		/// @Return	: NONE
		virtual void	OnClose(uint64_t nConnId, int nReason) = 0;

		IListener() : pSender(nullptr) {}
		virtual ~IListener() {}

		ServerSocket *	pSender;
	};

	/// @Brief	: “127.0.0.1”的Ip转换成uint32_t的形式
	/// @Param	: szIp		IP的字串形式
	/// @Return	: 返回转换后的uint32_t形式的IP
	extern uint32_t		GetIpInt(std::string & szIp);

	/// @Brief	: uint32_t的Ip转换成“127.0.0.1”的形式
	/// @Param	: uRemoteIp	IP的uint32形式
	/// @Return	: 返回转换后的“127.0.0.1”形式的IP
	extern std::string	GetIpString(uint32_t uRemoteIp);

}}

#endif//!	__ENGINE_NETWORK_HPP_INCLUDE__
